/********************************************************************
	created:	13:2:2007   10:34
	filename: 	SimpleLogger.h
	author:		saltyshrimp
	
	purpose:	a simple logger help do logging, has four log levels,
	            and four log types(cancel the xml type)
*********************************************************************/

#ifndef SIMPLE_LOGGER_H
#define SIMPLE_LOGGER_H

#include <fstream>
#include <string>


class SimpleLogger
{
public:
	enum LogLevel
	{
		LL_DEBUG,
		LL_INFO,
		LL_WARNING,
		LL_ERROR,
	};

	enum LogType
	{
		LT_CONSOLE  = 1,
		LT_DEBUGWND = 2,
		LT_TEXT     = 4,
		LT_HTML     = 8,
//		LT_XML      = 16,
		LT_ALL      = 31
	};

public:
	static SimpleLogger& Instance();

	// to set the logType, you can use "|" operation to union the LogTypes
	void Open(LogLevel level = LL_DEBUG, int logType = LT_ALL, std::string logFile = "log");

	// you can call Close() yourself, or it will be called by the destructor automatically
	void Close();

	// if you don't want to log the date and time, set them false
	void EnableLogDate(bool logDate = true) { this->logDate = logDate; }
	void EnableLogTime(bool lobTime = true) { this->logTime = logTime; }

	// usage of << :
	// must log a level first to begin a log, else the next calls to << will not work;
	// to end a log, log a string "\n";
	// if you log several levels before a "\n", the log will only begin on the last level'
	// NOTE: don't use to local log
	SimpleLogger& operator << (LogLevel level);
	SimpleLogger& operator << (int i);
	SimpleLogger& operator << (unsigned int ui);
	SimpleLogger& operator << (long l);
	SimpleLogger& operator << (unsigned long ul);
	SimpleLogger& operator << (float f);
	SimpleLogger& operator << (double d);
	SimpleLogger& operator << (const char* chs);
	SimpleLogger& operator << (std::string str);

	// you can use %s for const char*, %d for int, %u for unsigned int, %ld for long,
	// %lu for unsigned long, %f for float and double
	void Log(LogLevel level, const char* format, ...);

	// local log : specify another file to log, use LT_TEXT, specially, when you
	//             want to take some log out of the globe log, use it!!
	//  NOTE : the local log also log the globe log, use LL_DEBUG
	void LocalLog(std::string logFile, const char* format, ...);

private:
	SimpleLogger();
	SimpleLogger(const SimpleLogger&);
	SimpleLogger& operator = (const SimpleLogger&);
	~SimpleLogger();

	inline std::string GetLevelStr(LogLevel level, bool html = false);
	inline std::string GetLevelClr(LogLevel level);
	void GenerateLineHeading();

	template<typename T> 
	inline std::string NumToStr(T n);

	std::string GetDateAndTime();
	std::string ParseParams(va_list& argList, const char* format);
	void ConvertBreak(std::string& msg, bool html);
	void WriteLog(const std::string& dateTimeStr, LogLevel level, const std::string& msg);
private:
	std::ofstream textLog;
	std::ofstream htmlLog;
//	std::ofstream xmlLog;

	std::string htmlLineHeading;
	std::string textLineHeading;

	int logType;
	LogLevel logLevel;
	bool logDate;
	bool logTime;

	bool localLogging;
    std::string localLogStr;
	LogLevel localLogLevel;
	std::ofstream localLog;
	std::string  localLogFile;
};


#endif

